/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.interpreter.backends.jena;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Laurent WOUTERS
 */
public class JenaGraphTranslator {
    protected JenaRepository repository;

    public JenaGraphTranslator(JenaRepository repo) {
        repository = repo;
    }

    public Translation translate(Collection<xowl.interpreter.backends.rdf.RDFTriple> triples) {
        Job job = new Job();
        job.addTriples(triples);
        return job.execute();
    }

    public static class Translation {
        protected Collection<com.hp.hpl.jena.graph.Triple> jenaTriples;
        protected Map<xowl.interpreter.backends.rdf.XOWLVariableNode, com.hp.hpl.jena.sparql.core.Var> dictJenaVars;
        protected Map<com.hp.hpl.jena.sparql.core.Var, xowl.interpreter.backends.rdf.XOWLVariableNode> dictXOWLVars;

        public Collection<com.hp.hpl.jena.graph.Triple> getTriples() { return jenaTriples; }
        public xowl.interpreter.backends.rdf.XOWLVariableNode getVariableNode(com.hp.hpl.jena.sparql.core.Var node) { return dictXOWLVars.get(node); }
        public com.hp.hpl.jena.sparql.core.Var getVariableNode(xowl.interpreter.backends.rdf.XOWLVariableNode node) { return dictJenaVars.get(node); }
        public Collection<com.hp.hpl.jena.sparql.core.Var> getVariables() { return dictJenaVars.values(); }
        
        public Translation(Collection<com.hp.hpl.jena.graph.Triple> triples, Map<xowl.interpreter.backends.rdf.XOWLVariableNode, com.hp.hpl.jena.sparql.core.Var> toJena, Map<com.hp.hpl.jena.sparql.core.Var, xowl.interpreter.backends.rdf.XOWLVariableNode> toXOWL) {
            jenaTriples = triples;
            dictJenaVars = toJena;
            dictXOWLVars = toXOWL;
        }
    }

    protected class Job {
        protected Collection<xowl.interpreter.backends.rdf.RDFTriple> xOWLTriples;
        protected Collection<com.hp.hpl.jena.graph.Triple> jenaTriples;
        protected Map<xowl.interpreter.backends.rdf.XOWLVariableNode, com.hp.hpl.jena.sparql.core.Var> dictJenaVars;
        protected Map<com.hp.hpl.jena.sparql.core.Var, xowl.interpreter.backends.rdf.XOWLVariableNode> dictXOWLVars;

        public Job() {
            xOWLTriples = new ArrayList<xowl.interpreter.backends.rdf.RDFTriple>();
            jenaTriples = new ArrayList<com.hp.hpl.jena.graph.Triple>();
            dictJenaVars = new HashMap<xowl.interpreter.backends.rdf.XOWLVariableNode, com.hp.hpl.jena.sparql.core.Var>();
            dictXOWLVars = new HashMap<com.hp.hpl.jena.sparql.core.Var, xowl.interpreter.backends.rdf.XOWLVariableNode>();
        }

        public void addTriple(xowl.interpreter.backends.rdf.RDFTriple triple) { xOWLTriples.add(triple); }
        public void addTriples(Collection<xowl.interpreter.backends.rdf.RDFTriple> triples) { xOWLTriples.addAll(triples); }

        public Translation execute() {
            for (xowl.interpreter.backends.rdf.RDFTriple triple : xOWLTriples)
                jenaTriples.add(translate_triple(triple));
            return new Translation(jenaTriples, dictJenaVars, dictXOWLVars);
        }

        protected com.hp.hpl.jena.graph.Triple translate_triple(xowl.interpreter.backends.rdf.RDFTriple triple) {
            com.hp.hpl.jena.graph.Node subject = translate_subject(triple.getSubject());
            com.hp.hpl.jena.graph.Node prop = translate_property(triple.getProperty());
            com.hp.hpl.jena.graph.Node object = translate_object(triple.getObject());
            return new com.hp.hpl.jena.graph.Triple(subject, prop, object);
        }

        protected com.hp.hpl.jena.graph.Node translate_subject(xowl.interpreter.backends.rdf.RDFSubjectNode node) {
            if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.IRIReference)
                return repository.getJenaResource((xowl.interpreter.backends.rdf.RDFIRIReference)node).asNode();
            else if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.Blank || node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.Anonymous)
                return repository.getJenaResource((xowl.interpreter.backends.rdf.RDFBlankNode)node).asNode();
            return getJenaVar((xowl.interpreter.backends.rdf.XOWLVariableNode)node);
        }
        protected com.hp.hpl.jena.graph.Node translate_property(xowl.interpreter.backends.rdf.RDFProperty node) {
            if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.IRIReference)
                return repository.getJenaResource((xowl.interpreter.backends.rdf.RDFIRIReference)node).asNode();
            return getJenaVar((xowl.interpreter.backends.rdf.XOWLVariableNode)node);
        }
        protected com.hp.hpl.jena.graph.Node translate_object(xowl.interpreter.backends.rdf.RDFNode node) {
            if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.IRIReference)
                return repository.getJenaResource((xowl.interpreter.backends.rdf.RDFIRIReference)node).asNode();
            else if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.Blank || node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.Anonymous)
                return repository.getJenaResource((xowl.interpreter.backends.rdf.RDFBlankNode)node).asNode();
            else if (node.getNodeType() == xowl.interpreter.backends.rdf.RDFNodeType.Literal)
                return repository.getJenaLiteral((xowl.interpreter.backends.rdf.RDFLiteralNode)node).asNode();
            return getJenaVar((xowl.interpreter.backends.rdf.XOWLVariableNode)node);
        }
        protected com.hp.hpl.jena.graph.Node getJenaVar(xowl.interpreter.backends.rdf.XOWLVariableNode node) {
            if (dictJenaVars.containsKey(node))
                return dictJenaVars.get(node);
            com.hp.hpl.jena.sparql.core.Var var = com.hp.hpl.jena.sparql.core.Var.alloc(node.getVariable().getName());
            dictJenaVars.put(node, var);
            dictXOWLVars.put(var, node);
            return var;
        }
    }
}
